package com.ying.user.controller.handler;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.json.JSONUtil;
import com.ying.common.entity.Response;
import com.ying.common.entity.ResponseCode;
import com.ying.common.exception.BaseException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.method.annotation.MethodArgumentTypeMismatchException;
import org.springframework.web.servlet.NoHandlerFoundException;

import javax.validation.ConstraintViolationException;

/**
 * 全局统一异常处理
 */
@ControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger logger = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    @ExceptionHandler(value = Exception.class)
    @ResponseBody
    public Response handlerException(Exception e) {
        if (e instanceof NoHandlerFoundException) {
            logger.error("【全局异常拦截】NoHandlerFoundException: 请求方法 {}, 请求路径 {}", ((NoHandlerFoundException) e).getRequestURL(), ((NoHandlerFoundException) e).getHttpMethod());
            return new Response().userLoginDefined(ResponseCode.VALIDATE_FAILED);
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            logger.error("【全局异常拦截】HttpRequestMethodNotSupportedException: 当前请求方式 {}, 支持请求方式 {}", ((HttpRequestMethodNotSupportedException) e).getMethod(), JSONUtil.toJsonStr(((HttpRequestMethodNotSupportedException) e).getSupportedHttpMethods()));
            return new Response().userLoginDefined(ResponseCode.HTTP_BAD_METHOD);
        } else if (e instanceof MethodArgumentNotValidException) {
            logger.error("【全局异常拦截】MethodArgumentNotValidException", e);
            return new Response().userDefined(ResponseCode.BAD_REQUEST.getCode(), ((MethodArgumentNotValidException) e).getBindingResult()
                    .getAllErrors()
                    .get(0)
                    .getDefaultMessage(), null);
        } else if (e instanceof ConstraintViolationException) {
            logger.error("【全局异常拦截】ConstraintViolationException", e);
            return new Response().userDefined(ResponseCode.BAD_REQUEST.getCode(), CollUtil.getFirst(((ConstraintViolationException) e).getConstraintViolations())
                    .getMessage(), null);
        } else if (e instanceof MethodArgumentTypeMismatchException) {
            logger.error("【全局异常拦截】MethodArgumentTypeMismatchException: 参数名 {}, 异常信息 {}", ((MethodArgumentTypeMismatchException) e).getName(), ((MethodArgumentTypeMismatchException) e).getMessage());
            return new Response().userLoginDefined(ResponseCode.BAD_REQUEST);
        } else if (e instanceof HttpMessageNotReadableException) {
            logger.error("【全局异常拦截】HttpMessageNotReadableException: 错误信息 {}", ((HttpMessageNotReadableException) e).getMessage());
            return new Response().userLoginDefined(ResponseCode.BAD_REQUEST);
        } else if (e instanceof BadCredentialsException) {
            logger.error("【全局异常拦截】BadCredentialsException: 错误信息 {}", e.getMessage());
            return new Response().userLoginDefined(ResponseCode.USERNAME_PASSWORD_ERROR);
        } else if (e instanceof DisabledException) {
            logger.error("【全局异常拦截】BadCredentialsException: 错误信息 {}", e.getMessage());
            return new Response().userLoginDefined(ResponseCode.USER_DISABLED);
        } else if (e instanceof BaseException) {
            logger.error("【全局异常拦截】DataManagerException: 状态码 {}, 异常信息 {}", ((BaseException) e).getCode(), e.getMessage());
            return new Response().exception((BaseException) e);
        }

        logger.error("【全局异常拦截】: 异常信息 {} ", e.getMessage());
        return new Response().userLoginDefined(ResponseCode.FAILED);
    }
}
